feat(spring-jakarta): [Queue Instrumentation 3] Add Kafka producer instrumentation#5254
feat(spring-jakarta): [Queue Instrumentation 3] Add Kafka producer instrumentation#5254adinauer wants to merge 4 commits intofeat/queue-instrumentation-samplefrom
Conversation
Add SentryKafkaProducerWrapper that overrides doSend to create queue.publish spans for all KafkaTemplate send operations. Injects sentry-trace, baggage, and sentry-task-enqueued-time headers for distributed tracing and receive latency calculation. Add SentryKafkaProducerBeanPostProcessor to automatically wrap KafkaTemplate beans. Co-Authored-By: Claude <noreply@anthropic.com>
Semver Impact of This PR🟡 Minor (new features) 📋 Changelog PreviewThis is how your changes will appear in the changelog. New Features ✨
Internal Changes 🔧Deps
Other
🤖 This preview updates automatically when you update the PR. |
|
Sentry Build Distribution
|
Performance metrics 🚀
|
…oducerInterceptor Replace the KafkaTemplate subclass approach with a Kafka-native ProducerInterceptor. The BeanPostProcessor now sets the interceptor on the existing KafkaTemplate instead of replacing the bean, which preserves any custom configuration on the template. Existing customer interceptors are composed using Spring's CompositeProducerInterceptor. If reflection fails to read the existing interceptor, a warning is logged. Co-Authored-By: Claude <noreply@anthropic.com>
TransactionContext constructor requires ScopesAdapter.getOptions() to be non-null for thread checker access. Add initForTest/close to ensure Sentry is properly initialized during tests. Co-Authored-By: Claude <noreply@anthropic.com>
| try { | ||
| injectHeaders(record.headers(), span); | ||
| } catch (Throwable ignored) { | ||
| // Header injection must not break the send |
There was a problem hiding this comment.
Do we want to have any info on the fact, that header injection failed? A log for example?
|
|
||
| final @Nullable BaggageHeader baggageHeader = tracingHeaders.getBaggageHeader(); | ||
| if (baggageHeader != null) { | ||
| headers.remove(baggageHeader.getName()); |
There was a problem hiding this comment.
Do we want to remove the full baggageHeader here? Would that not potentially remove baggage information from other instrumentation libraries? Ok with it if its intentional, just raising the point
| final @NotNull KafkaTemplate<?, ?> template = (KafkaTemplate<?, ?>) bean; | ||
| final @Nullable ProducerInterceptor<?, ?> existing = getExistingInterceptor(template); | ||
|
|
||
| if (existing instanceof SentryProducerInterceptor) { |
There was a problem hiding this comment.
one possible edge case here: If for some reason a user already manually registered the SentryInterceptor and another one in a composite we would wrap that again and have SentryInterceptor registered twice
PR Stack (Queue Instrumentation)
📜 Description
Add Kafka producer instrumentation to
sentry-spring-jakarta:SentryKafkaProducerWrapper— overridesdoSendto createqueue.publishspans for allKafkaTemplatesend operations. Injectssentry-trace,baggage, andsentry-task-enqueued-timeheaders for distributed tracing and receive latency calculation.SentryKafkaProducerBeanPostProcessor— automatically wrapsKafkaTemplatebeans.💡 Motivation and Context
Producer-side instrumentation is needed to create publish spans and inject trace propagation headers into Kafka messages.
💚 How did you test it?
Unit tests for
SentryKafkaProducerWrapperandSentryKafkaProducerBeanPostProcessor.📝 Checklist
sendDefaultPIIis enabled.🔮 Next steps